﻿using System;
using System.Collections.Generic;
using System.Linq;
using PhotoBlog.Core.Models;
using PhotoBlog.Core.Models.Albums;
using PhotoBlog.Core.Models.Photos;
using PhotoBlog.Models.ClientModels;
using PhotoBlog.Models.Portfolio;
using WebGrease.Css.Extensions;

namespace PhotoBlog.Models.Builders
{
    public class MainVmBuilder : IMainVmBuilder
    {
        private readonly IPhotoRepository photoRepository;
        private readonly IAlbumRepository albumRepository;
        private const string ThumbnailFolder = "T";

        public MainVmBuilder(IPhotoRepository photoRepository, IAlbumRepository albumRepository)
        {
            this.photoRepository = photoRepository;
            this.albumRepository = albumRepository;
        }

        public MainViewM BuildPhotos(GetPhotosParams getPhotosParams)
        {
            var photos = photoRepository
                .GetPhotosByAlbumId(getPhotosParams.AlbumId)
                .OrderByDescending(p => p.Date)
                .Skip(getPhotosParams.Skip)
                .Take(getPhotosParams.Take)
                .ToArray();
            return BuildPhotos(getPhotosParams, photos);
        }

        private static MainViewM BuildPhotos(GetPhotosParams getPhotosParams, Photo[] photos)
        {
            var model = new MainViewM
            {
                PhotoM = photos
                    .Select((p, index) =>
                        new PhotoM
                        {
                            Id = p.PhotoId,
                            Description = p.Description,
                            Name = p.PhotoName,
                            Path = PathBuild(p),
                            Thumbnail = ThumbnailPathBuild(p),
                            Date = p.Date.ToShortDateString(),
                            Day = p.Date.DayOfYear,
                            Music = p.Music.Trim(),
                            Views = p.Statistic != null ? p.Statistic.Views : 0
                        }).ToArray()
            };
            model.Skip = getPhotosParams.Skip + model.PhotoM.Length;
            model.Scrolled = photos.Any();
            return model;
        }

        private static DayPhotoM BuildDayPhoto(Photo photo, PagingM paging)
        {
            var modelDay = new DayPhotoM
            {
                PagingM = paging,
                PhotoM =
                    new PhotoM
                    {
                        Id = photo.PhotoId,
                        Description = photo.Description,
                        Name = photo.PhotoName,
                        Path = PathBuild(photo),
                        Thumbnail = ThumbnailPathBuild(photo),
                        Date = photo.Date.ToShortDateString(),
                        Day = photo.Date.DayOfYear,
                        Music = photo.Music.Trim(),
                        Views = photo.Statistic != null ? photo.Statistic.Views : 0
                    }
            };
            return modelDay;
        }

        public AlbumsViewM BuildAlbums()
        {
            var albums = albumRepository.GetAlbums(withHidden: false);
            if (albums.Any())
            {
                var model = new AlbumsViewM
                {
                    AlbumMs = albums
                        .ToArray()
                        .Where(a => a.Photos.Any())
                        .Select(a =>
                        {
                            var photo = a.Photos.FirstOrDefault();

                            var logo = photo != null ? ThumbnailPathBuild(photo) : "Content/images/preview.png";
                            return new AlbumM
                            {
                                AlbumId = a.AlbumId,
                                Description = a.Description,
                                Logo = logo,
                                Name = a.AlbumName,
                                Photos = a.Photos.Count
                            };
                        })
                        .ToArray()
                };
                return model;
            }
            return new AlbumsViewM();
        }

        public AlbumPhotosViewM BuildPhotoAlbums(int id)
        {
            var album = albumRepository.GetAlbum(id, withHidden: false);
            var albums = albumRepository.GetAlbums(withHidden: false);
            var photos = album.Photos.ToArray();

            var model = new AlbumPhotosViewM
            {
                Albums = albums
                    .Where(a => a.Photos.Any())
                    .Select(a => new AlbumM
                    {
                        AlbumId = a.AlbumId,
                        Name = a.AlbumName
                    })
                    .ToArray(),
                Album = new AlbumM
                {
                    AlbumId = album.AlbumId,
                    Description = album.Description,
                    Name = album.AlbumName
                },
                Photos = photos.Select((p, index) => new PhotoM
                {
                    Id = p.PhotoId,
                    Date = p.Date.ToShortDateString(),
                    Description = p.Description,
                    Name = p.PhotoName,
                    Path = PathBuild(p),
                    Thumbnail = ThumbnailPathBuild(p),
                    Music = p.Music.Trim(),
                    Views = p.Statistic != null ? p.Statistic.Views : 0
                }).ToArray()
            };
            return model;
        }

        public DayPhotoM BuildDayPhoto(GetPhotosParams getPhotosParams)
        {
            var photos = photoRepository
                .GetPhotosByAlbumId(getPhotosParams.AlbumId)
                .OrderByDescending(p => p.Date);

            if (getPhotosParams.NumberDay != null)
            {
                var array = photos.ToArray();
                var paging = new PagingM();

                var photoArray = array
                    .Select((p, index) =>
                        new
                        {
                            index,
                            photo = p
                        })
                    .ToArray();

                var photoElem =
                    photoArray
                    .FirstOrDefault(p => p.photo.Date.DayOfYear == getPhotosParams.NumberDay);
                if (photoElem != null)
                {
                    paging.CurrentPage = photoArray[photoElem.index].photo.Date.DayOfYear;
                    paging.NextPage = photoElem.index == 0 ? photoArray.Last().photo.Date.DayOfYear : photoArray[photoElem.index - 1].photo.Date.DayOfYear;
                    paging.PrevPage = photoElem.index == photoArray.Length - 1 ? photoArray.First().photo.Date.DayOfYear : photoArray[photoElem.index + 1].photo.Date.DayOfYear;

                    photoRepository.AddView(photoElem.photo.PhotoId);
                    return BuildDayPhoto(photoElem.photo, paging);
                }
                var currentPhoto = photos.FirstOrDefault();
                if (currentPhoto != null)
                {
                    return BuildDayPhoto(currentPhoto, paging);
                }
                return new DayPhotoM();
            }

            return new DayPhotoM();
        }

        private PagingM GetPaging(Photo[] array, Photo p, int i)
        {
            var paging = new PagingM();
            var previdx = i - 1;
            var nextidx = i + 1;
            var alength = array.Length - 1;
            paging.PrevPage = previdx == -1 ? array.Length : alength >= previdx && p.Date.DayOfYear != array[previdx].Date.DayOfYear ? array[previdx].Date.DayOfYear : alength;
            paging.NextPage = alength >= nextidx && p.Date.DayOfYear != array[nextidx].Date.DayOfYear ? array[nextidx].Date.DayOfYear : 1;
            return paging;
        }

        public bool SavePhoto(PhotoM photo)
        {
            var oldPhoto = photoRepository.Find(photo.Id);
            oldPhoto.Description = photo.Description ?? "";
            oldPhoto.Music = photo.Music ?? "";
            try
            {
                photoRepository.Save(oldPhoto);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public PortfolioViewModel BuildPortfolio()
        {
            var albumId = 1;//365 лиц
            var album = albumRepository.GetAlbum(albumId, withHidden: false);
            var photos = album.Photos.OrderByDescending(p => p.Date).ToArray();

            var model = new PortfolioViewModel
            {
                PortfolioPhoto =
                    photos.Select(p => new PortfolioPhotoM
                    {
                        Day = p.Date.DayOfYear.ToString(),
                        ImageUrl = PathBuild(p),
                        ImageThumbUrl = ThumbnailPathBuild(p)
                    }).ToArray()
            };

            return model;
        }

        private static string ThumbnailPathBuild(Photo photo)
        {
            return string.Format("{0}/{1}/{2}", photo.Path, ThumbnailFolder, photo.PhotoName);
        }

        private static string PathBuild(Photo photo)
        {
            return string.Format("{0}/{1}", photo.Path, photo.PhotoName);
        }
    }
}